#include <stdio.h>
#include <unistd.h>
#include <functional>

// TEST1
#define STL_printf(format, args...) (printf(format, ##args))

// TEST2

#define STL_error(format, args...) (fprintf(STL_Files::getInstance()->stl_stderr, format, ##args))

// TEST3
#define ESC_START "\033["
#define ESC_END "\033[0m"
#define COLOR_FATAL "31;40;5m"
#define COLOR_ALERT "31;40;1m"
#define COLOR_CRIT "31;40;1m"
#define COLOR_ERROR "31;40;1m"
#define COLOR_WARN "33;40;1m"
#define COLOR_NOTICE "34;40;1m"
#define COLOR_INFO "32;40;1m"
#define COLOR_DEBUG "36;40;1m"
#define COLOR_TRACE "37;40;1m"

#define STLOG_Info(format, args...) (printf(ESC_START COLOR_INFO "[INFO]-[%s]-[%s]-[%d]:" format ESC_END, __FILE__, __FUNCTION__, __LINE__, ##args))

#define STLOG_Debug(format, args...) (printf(ESC_START COLOR_DEBUG "[DEBUG]-[%s]-[%s]-[%d]:" format ESC_END, __FILE__, __FUNCTION__, __LINE__, ##args))

#define STLOG_Warn(format, args...) (printf(ESC_START COLOR_WARN "[WARN]-[%s]-[%s]-[%d]:" format ESC_END, __FILE__, __FUNCTION__, __LINE__, ##args))

#define STLOG_Error(format, args...) (printf(ESC_START COLOR_ERROR "[ERROR]-[%s]-[%s]-[%d]:" format ESC_END, __FILE__, __FUNCTION__, __LINE__, ##args))

class STL_Files
{
public:
    static STL_Files *getInstance();

private:
    STL_Files();
    ~STL_Files() = default;

public:
    FILE *stl_stdout;
    FILE *stl_stderr;
};

STL_Files::STL_Files()
{
    stl_stdout = stdout;
    stl_stderr = stderr;
}

STL_Files *STL_Files::getInstance()
{
    static STL_Files instance;
    return &instance;
}

#define STL_STATUS_CALLBACK(statusEnum)                                               \
public:                                                                               \
    typedef std::function<void(statusEnum)> StatusCallback;                           \
    void setStatusCallback(StatusCallback callback) { m_statusCallback = callback; }; \
    statusEnum getStatus(void) { return m_status; };                                  \
                                                                                      \
protected:                                                                            \
    statusEnum m_status;                                                              \
    StatusCallback m_statusCallback;                                                  \
    void setStatus(statusEnum status)                                                 \
    {                                                                                 \
        m_status = status;                                                            \
        if (m_statusCallback)                                                         \
        {                                                                             \
            m_statusCallback(m_status);                                               \
        }                                                                             \
    };

class TestClass
{
public:
    typedef enum Status_e
    {
        STATUS1,
        STATUS2
    } Status;

public:
    STL_STATUS_CALLBAC(Status);

public:
    void changeStatus(Status status)
    {
        setStatus(status);
    };
};

/**
 * @brief 
 * 
 * #include <stdio.h>
 * int printf（const char * format ，...）; 标准输出
 * int fprintf（FILE * stream ，const char * format ，...）; 定向输出 stdout stderr
 * int dprintf（int fd ，const char * format ，...）; 文件描述符，文件句柄，嵌套字
 * int sprintf（char * str ，const char * format ，...）; 内存指针
 * int snprintf（char * str ，size_t size ，const char * format ，...）; 内存指针+长度
 * 
 * @param argn 
 * @param argv 
 * @return int 
 */
int main(int argn, char **argv)
{
    // printf("TEST1--------------------------------------------\n");
    // STL_printf("TEST:%d\nHello World!\n", 1);
    // printf("TEST2--------------------------------------------\n");
    // STL_error("TEST:%d\nHello World!\n", 2);
    // printf("TEST3--------------------------------------------\n");
    // Msg_Info("TEST:%d\nMsg_Info\n", 3);
    // Msg_Debug("TEST:%d\nMsg_Debug\n", 3);
    // Msg_Warn("TEST:%d\nMsg_Warn\n", 3);
    // Msg_Error("TEST:%d\nMsg_Error\n", 3);
    printf("TEST4--------------------------------------------\n");
    TestClass *test = new TestClass();
    test->setStatusCallback([=](TestClass::Status status) {
        Msg_Debug("status%d\n", status);
    });
    sleep(1);
    test->changeStatus(TestClass::STATUS1);
    sleep(1);
    test->changeStatus(TestClass::STATUS2);
    sleep(1);
    test->changeStatus(TestClass::STATUS1);
    sleep(1);
    test->changeStatus(TestClass::STATUS2);
    sleep(1);
    test->changeStatus(TestClass::STATUS1);
    sleep(1);
    test->changeStatus(TestClass::STATUS2);
    printf("-------------------------------------------------\n");

    return 0;
}